//手写实现MyPromise源码

 // 判断变量否为function
 const isFunction = variable => typeof variable === 'function'
 // 定义Promise的三种状态常量
 const PENDING = 'PENDING'
 const FULFILLED = 'FULFILLED'
 const REJECTED = 'REJECTED'

 class MyPromise {
   constructor (handle) {
     if (!isFunction(handle)) {
       throw new Error('MyPromise must accept a function as a parameter')
     }
     // 添加状态
     this._status = PENDING
     // 添加状态
     this._value = undefined
     // 添加成功回调函数队列
     this._fulfilledQueues = []
     // 添加失败回调函数队列
     this._rejectedQueues = []
     // 执行handle
     try {
       handle(this._resolve.bind(this), this._reject.bind(this)) 
     } catch (err) {
       this._reject(err)
     }
   }
   // 添加resovle时执行的函数
   _resolve (val) {
     const run = () => {
       if (this._status !== PENDING) return
       // 依次执行成功队列中的函数，并清空队列
       const runFulfilled = (value) => {
         let cb;
         while (cb = this._fulfilledQueues.shift()) {
           cb(value)
         }
       }
       // 依次执行失败队列中的函数，并清空队列
       const runRejected = (error) => {
         let cb;
         while (cb = this._rejectedQueues.shift()) {
           cb(error)
         }
       }
       /* 如果resolve的参数为Promise对象，则必须等待该Promise对象状态改变后,
         当前Promsie的状态才会改变，且状态取决于参数Promsie对象的状态
       */
       if (val instanceof MyPromise) {
         val.then(value => {
           this._value = value
           this._status = FULFILLED
           runFulfilled(value)
         }, err => {
           this._value = err
           this._status = REJECTED
           runRejected(err)
         })
       } else {
         this._value = val
         this._status = FULFILLED
         runFulfilled(val)
       }
     }
     // 为了支持同步的Promise，这里采用异步调用
     setTimeout(run, 0)
   }
   // 添加reject时执行的函数
   _reject (err) { 
     if (this._status !== PENDING) return
     // 依次执行失败队列中的函数，并清空队列
     const run = () => {
       this._status = REJECTED
       this._value = err
       let cb;
       while (cb = this._rejectedQueues.shift()) {
         cb(err)
       }
     }
     // 为了支持同步的Promise，这里采用异步调用
     setTimeout(run, 0)
   }
   // 添加then方法
   then (onFulfilled, onRejected) {
     const { _value, _status } = this
     // 返回一个新的Promise对象
     return new MyPromise((onFulfilledNext, onRejectedNext) => {
       // 封装一个成功时执行的函数
       let fulfilled = value => {
         try {
           if (!isFunction(onFulfilled)) {
             onFulfilledNext(value)
           } else {
             let res =  onFulfilled(value);
             if (res instanceof MyPromise) {
               // 如果当前回调函数返回MyPromise对象，必须等待其状态改变后在执行下一个回调
               res.then(onFulfilledNext, onRejectedNext)
             } else {
               //否则会将返回结果直接作为参数，传入下一个then的回调函数，并立即执行下一个then的回调函数
               onFulfilledNext(res)
             }
           }
         } catch (err) {
           // 如果函数执行出错，新的Promise对象的状态为失败
           onRejectedNext(err)
         }
       }
       // 封装一个失败时执行的函数
       let rejected = error => {
         try {
           if (!isFunction(onRejected)) {
             onRejectedNext(error)
           } else {
               let res = onRejected(error);
               if (res instanceof MyPromise) {
                 // 如果当前回调函数返回MyPromise对象，必须等待其状态改变后在执行下一个回调
                 res.then(onFulfilledNext, onRejectedNext)
               } else {
                 //否则会将返回结果直接作为参数，传入下一个then的回调函数，并立即执行下一个then的回调函数
                 onFulfilledNext(res)
               }
           }
         } catch (err) {
           // 如果函数执行出错，新的Promise对象的状态为失败
           onRejectedNext(err)
         }
       }
       switch (_status) {
         // 当状态为pending时，将then方法回调函数加入执行队列等待执行
         case PENDING:
           this._fulfilledQueues.push(fulfilled)
           this._rejectedQueues.push(rejected)
           break
         // 当状态已经改变时，立即执行对应的回调函数
         case FULFILLED:
           fulfilled(_value)
           break
         case REJECTED:
           rejected(_value)
           break
       }
     })
   }
   // 添加catch方法
   catch (onRejected) {
     return this.then(undefined, onRejected)
   }
   // 添加静态resolve方法
   static resolve (value) {
     // 如果参数是MyPromise实例，直接返回这个实例
     if (value instanceof MyPromise) return value
     return new MyPromise(resolve => resolve(value))
   }
   // 添加静态reject方法
   static reject (value) {
     return new MyPromise((resolve ,reject) => reject(value))
   }
   // 添加静态all方法
   static all (list) {
     return new MyPromise((resolve, reject) => {
       /**
        * 返回值的集合
        */
       let values = []
       let count = 0
       for (let [i, p] of list.entries()) {
         // 数组参数如果不是MyPromise实例，先调用MyPromise.resolve
         this.resolve(p).then(res => {
           values[i] = res
           count++
           // 所有状态都变成fulfilled时返回的MyPromise状态就变成fulfilled
           if (count === list.length) resolve(values)
         }, err => {
           // 有一个被rejected时返回的MyPromise状态就变成rejected
           reject(err)
         })
       }
     })
   }
   // 添加静态race方法
   static race (list) {
     return new MyPromise((resolve, reject) => {
       for (let p of list) {
         // 只要有一个实例率先改变状态，新的MyPromise的状态就跟着改变
         this.resolve(p).then(res => {
           resolve(res)
         }, err => {
           reject(err)
         })
       }
     })
   }
   finally (cb) {
     return this.then(
       value  => MyPromise.resolve(cb()).then(() => value),
       reason => MyPromise.resolve(cb()).then(() => { throw reason })
     );
   }
 }







 const p = new MyPromise((resolve, reject) => {
    setTimeout(function() {
        // resolve('success') // 异步调用的时候，this.status一直是pending状态,不会执行代码了，因此要改装成发布订阅者模式
        reject('failed')
    }, 1000)
    // resolve('success') // 走了成功就不会走失败了
    // throw new Error('失败') // 失败了也会走resolve
    // reject('failed')
})
p.then((res) => {
    console.log(res)
}, (err) => {
    console.log(err)
})
p.then((res) => {
    console.log(res)
}, (err) => {
    console.log(err)
})
p.then((res) => {
    console.log(res)
}, (err) => {
    console.log(err)
})
